package com.yibo.feign;

import com.yibo.support.context.SpringContext;
import com.yibo.support.exception.YBErrorResult;
import com.yibo.support.exception.YBException;
import com.yibo.support.helper.Assert;
import com.yibo.support.helper.JsonHelper;
import com.yibo.support.helper.ObjectHelper;
import org.springframework.http.*;
import org.springframework.util.LinkedMultiValueMap;
import org.springframework.util.MultiValueMap;
import org.springframework.web.client.RestTemplate;

import java.util.Map;

import static com.yibo.support.constant.MsgConstant.SYSTEM_SERVER_EXCEPTION;
import static com.yibo.support.constant.YBConstant.REQUEST_BODY_TYPE;
import static com.yibo.support.constant.YBConstant.REQUEST_PARM_TYPE;

/**
 * restHelper
 *
 * @author zhanglei
 */
public class RestHelper {

    private static RestTemplate restTemplate(){
        return SpringContext.getBean(RestTemplate.class);
    }


    private static HttpHeaders httpHeaders(){
        return SpringContext.getBean(HttpHeaders.class);
    }


    public static <T>T rest(RestModel<T> model){
        return restOperate(model,httpHeaders());
    }

    public static <T>T  rest(RestModel<T> model,HttpHeaders headers){
        return restOperate(model,headers);
    }

    private static <T>T  restOperate(RestModel<T> model,HttpHeaders headers){
        String url = model.getUrl();
        HttpMethod method = model.getHttpMethod();
        if(ObjectHelper.hasEmpty(url,method)){
            throw new YBErrorResult("restTemplate request not found url and method!");
        }

        HttpEntity<Object> httpEntity = httpEntity(headers,model);
        Assert.notEmpty(SYSTEM_SERVER_EXCEPTION,httpEntity);
        ResponseEntity<T> responseEntity = restTemplate().exchange(url,method,httpEntity,model);
        if(responseEntity.getStatusCode()== HttpStatus.OK){
            return responseEntity.getBody();
        }else{
            throw new YBException(SYSTEM_SERVER_EXCEPTION);
        }
    }




    @SuppressWarnings("unchecked")
    private  static HttpEntity<Object> httpEntity(HttpHeaders headers,RestModel restModel){
        MediaType type = headers.getContentType();
        if(type != null){
            String subType = type.getSubtype();
            if(REQUEST_PARM_TYPE.equals(subType)){

                Object data = restModel.getData();
                if(data instanceof Map){
                    MultiValueMap<String, Object> postParameters = new LinkedMultiValueMap<>();
                    ((Map) data).forEach((key,value)->{
                        postParameters.add(key+"",value);
                    });

                    return new HttpEntity<>(postParameters,headers);
                }
            }else if(REQUEST_BODY_TYPE.equals(subType)){
                return new HttpEntity<>(restModel.getData(),headers);
            }
        }
        return null;
    }


    public static <T>RestModel<T>  restModel(String url,HttpMethod method,Object data){
        return new RestModel<T>()
                .setUrl(url)
                .setHttpMethod(method)
                .setData(data);
    }

}
